package com.yanggu.common.satoken;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.v7.core.collection.CollUtil;
import cn.hutool.v7.core.text.StrUtil;
import cn.hutool.v7.extra.spring.SpringUtil;
import cn.hutool.v7.json.JSONUtil;
import org.springframework.beans.factory.annotation.Value;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * sa-token 权限管理实现类
 */
public class SaPermissionImpl implements StpInterface {

    @Value("${sa-token.token-name}")
    private String tokenName;

    @Value("${sa-token.role-permission-bean-name:}")
    private String rolePermissionBeanName;

    /**
     * 返回一个账号所拥有的权限码集合
     *
     * @param loginId   账号id
     * @param loginType 账号类型
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {

        // 1. 声明权限码集合
        Set<String> set = new HashSet<>();

        // 2. 遍历角色列表，查询拥有的权限码
        for (String roleId : getRoleList(loginId, loginType)) {
            String key = getPermissionKey(roleId);
            List<String> permissionList = Optional.ofNullable(SaManager.getSaTokenDao().get(key))
                    .filter(StrUtil::isNotEmpty)
                    .map(jsonArray -> JSONUtil.toList(jsonArray, String.class)
                            .stream()
                            .distinct()
                            .toList())
                    .orElse(List.of());
            if (CollUtil.isEmpty(permissionList)) {
                // 从数据库查询这个角色 id 所拥有的权限列表
                RolePermissionInteface bean = getRolePermissionInteface();
                permissionList = bean.getPermissionList(loginId, roleId);
                // 查好后，set 到缓存中
                SaManager.getSaTokenDao().setObject(key, permissionList, 60 * 60 * 24);
            }
            if (CollUtil.isNotEmpty(permissionList)) {
                set.addAll(permissionList);
            }
        }

        // 3. 返回权限码集合
        return set.stream().toList();
    }

    /**
     * 返回一个账号所拥有的角色标识集合
     *
     * @param loginId   账号id
     * @param loginType 账号类型
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        String key = getRoleKey(loginId.toString());
        List<String> roleList = Optional.ofNullable(SaManager.getSaTokenDao().get(key))
                .filter(StrUtil::isNotEmpty)
                .map(jsonArray -> JSONUtil.toList(jsonArray, String.class)
                        .stream()
                        .distinct()
                        .toList())
                .orElse(List.of());
        if (CollUtil.isEmpty(roleList)) {
            // 从数据库查询这个账号id拥有的角色列表
            RolePermissionInteface bean = getRolePermissionInteface();
            roleList = bean.getRoleList(loginId, loginType);
            // 查好后，set 到缓存中
            SaManager.getSaTokenDao().setObject(key, roleList, 60 * 60 * 24);
        }
        return roleList;
    }

    private String getPermissionKey(String roleId) {
        return tokenName + ":permission:" + roleId;
    }

    private String getRoleKey(String loginId) {
        return tokenName + ":role:" + loginId;
    }

    // 获取角色权限接口
    private RolePermissionInteface getRolePermissionInteface() {
        if (StrUtil.isNotEmpty(rolePermissionBeanName)) {
            return SpringUtil.getBean(rolePermissionBeanName, RolePermissionInteface.class);
        }
        return SpringUtil.getBean(RolePermissionInteface.class);
    }

}
